package com.acme.bankapp.domain;

import com.acme.bankapp.domain.account.Account;
import com.acme.bankapp.exception.BankException;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Scanner;

public class Client implements Serializable {
    private String name;
    private Gender gender;
    private Account[] accounts = new Account[10];
    private int numberOfAccounts = 0;

    public Client(String name, Gender gender) {
        setName(name);
        setGender(gender);
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setGender(Gender gender) {
        this.gender = gender;
    }

    public Gender getGender() {
        return gender;
    }

    public Account[] getAccounts() {
        return Arrays.copyOf(accounts, numberOfAccounts);
    }

    public void addAccount (Account account) throws BankException {
        if (numberOfAccounts == 10) {
            throw new BankException("Client has 10 accounts. Cannot add more.");
        }
        accounts[numberOfAccounts] = account;
        numberOfAccounts++;
    }

    public String getClientSalutation() {
        return gender.getSalutation() + name;
    }

    public String toJSONString() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("Name=").append(getName()).append(";gender=");
        if (getGender() == Gender.MALE) {
            stringBuilder.append('m');
        } else {
            stringBuilder.append('f');
        }
        return stringBuilder.toString();
    }

    public static Client parseJSON(String clientJSON) throws BankException {
        Scanner clientString = new Scanner(clientJSON).useDelimiter("[=;]");
        clientString.next();
        String name = clientString.next();
        clientString.next();
        Gender gender;
        switch (clientString.next()) {
            case "m":
                gender = Gender.MALE;
                break;
            case "f":
                gender = Gender.FEMALE;
                break;
            default:
                throw new BankException();
        }
        return new Client(name, gender);
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("Client {")
                .append("name = ")
                .append(getClientSalutation())
                .append(", gender = '")
                .append(gender)
                .append('\'')
                .append(", accounts = ")
                .append(accountsToString())
                .append(", numberOfAccounts = ")
                .append(numberOfAccounts)
                .append('}');
        return sb.toString();
    }

    private String accountsToString() {
        StringBuffer sb = new StringBuffer();
        for (Account a : accounts) {
            if ( a != null ) {
                sb.append(a);
            }
        }
        return sb.toString();
    }

    public void printClientInfo() {
        System.out.println(this.toString());
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Client client = (Client) o;

        if (numberOfAccounts != client.numberOfAccounts) return false;
        if (!Arrays.equals(accounts, client.accounts)) return false;
        if (gender != client.gender) return false;
        if (name != null ? !name.equals(client.name) : client.name != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + (gender != null ? gender.hashCode() : 0);
        result = 31 * result + (accounts != null ? Arrays.hashCode(accounts) : 0);
        result = 31 * result + numberOfAccounts;
        return result;
    }
}
